using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Midgard
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Rectangle viewportrec;
        GameState gameState;

        EnemyManager enemyManager;
        ProjectileManager projectileManager;
        SoundsManager soundsManager;
        ArtifactManager artifactManager;


        Player player;
        //List<Enemy> enemies;


        // Keyboard states used to determine key presses.
        KeyboardState currentKeyboardState;
        KeyboardState previousKeyBoardState;

        // Gamepad states used to determine button presses.
        GamePadState currentGamePadState;
        GamePadState previousGamePadState;

        /* All the images */
        #region texture2ds
        Texture2D background;
        Texture2D playerSprite;
        Texture2D projectileTexture;
        Texture2D ship;
        Texture2D cannonball;
        Texture2D wizard;
        Texture2D fireball;
        Texture2D littleShip;
        Texture2D littleBall;
        Texture2D littleShipDeath1;
        Texture2D littleShipDeath2;
        Texture2D littleShipDeath3;
        Texture2D littleShipDeath4;
        Texture2D shipDeath1;
        Texture2D shipDeath2;
        Texture2D shipDeath3;
        Texture2D shipDeath4;
        Texture2D wizardDeath1;
        Texture2D wizardDeath2;
        Texture2D thor;
        Texture2D thorhurt1;
        Texture2D thorhurt2;
        Texture2D thorhurt3;
        Texture2D hammer;
        Texture2D openingscreen;
        Texture2D thorDeath1;
        Texture2D thorDeath2;
        Texture2D thorDeath3;
        Texture2D thorDeath4;
        Texture2D thorDeath5;
        //Texture2D HitBoxSprite;
        Texture2D endingscreen;
        Texture2D wave;
        #endregion

        TimeSpan bombTime;
        TimeSpan previousBombTime;
        TimeSpan fireTime;
        TimeSpan previousFireTime;


        int score;
        SpriteFont font;

        bool playingMenuMusic;
        bool playingBossMusic;
        bool hardMode = false;


        enum GameState
        {
            StartScreen, PlayingScreen, GameOverScreen
        };


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            score = 0;

            //soundsObj = new SoundsManager();

            bombTime = TimeSpan.FromSeconds(1f);
            fireTime = TimeSpan.FromSeconds(.35f);
            
            graphics.PreferredBackBufferWidth = 700;
            graphics.PreferredBackBufferHeight = 800;
            graphics.ApplyChanges();

            gameState = GameState.StartScreen;


            projectileManager = new ProjectileManager(viewportrec);
            playingBossMusic = true;
            playingMenuMusic = false;
            base.Initialize();

        }



        protected void swtichMusic()
        {
            switch (gameState)
            {
                case (GameState.StartScreen):
                    {
                        if (!playingMenuMusic)
                        {
                            soundsManager.PlayMusic("Menu");
                            playingMenuMusic = true;
                        }
                        break;
                    }
                case (GameState.PlayingScreen):
                    {
                        if (enemyManager.thorActive && !playingBossMusic)
                        {
                            //soundsObj.PlayMusic(soundsObj.forThor);
                            soundsManager.PlayMusic("ForThor!");
                            playingBossMusic = true;
                        }
                        //else if (enemyManager.thorActive && playingBossMusic)
                        //{
                        //    //nothing needed
                        //}
                        //else if (!enemyManager.thorActive && !playingBossMusic)
                        //{
                        //    //nothing needed
                        //}
                        else if (!enemyManager.thorActive && playingBossMusic)
                        {
                            //revert
                            //soundsObj.PlayMusic(soundsObj.gameplayMusic);
                            soundsManager.PlayMusic("Game");
                            playingBossMusic = false;
                        }
                        break;
                    }
                case (GameState.GameOverScreen):
                    {
                        if (!playingMenuMusic)
                        {
                            soundsManager.PlayMusic("Menu");
                            playingMenuMusic = true;
                        }
                        break;
                    }
            }


        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            #region textures
            background = Content.Load<Texture2D>("Mountainbackground");
            wave = Content.Load<Texture2D>("wave");
            endingscreen = Content.Load<Texture2D>("ending");
            playerSprite = Content.Load<Texture2D>("serpent_spritesheet");
            //HitBoxSprite = Content.Load<Texture2D>("blacksquare");
            projectileTexture = Content.Load<Texture2D>("shot");
            ship = Content.Load<Texture2D>("VikingShip1");
            cannonball = Content.Load<Texture2D>("viking_bullet");
            wizard = Content.Load<Texture2D>("wizard_blue");
            fireball = Content.Load<Texture2D>("fireball_projectile");
            littleShip = Content.Load<Texture2D>("viking_green");
            littleBall = Content.Load<Texture2D>("viking_green_bullet");
            littleShipDeath1 = Content.Load<Texture2D>("viking_green_death1");
            littleShipDeath2 = Content.Load<Texture2D>("viking_green_death2");
            littleShipDeath3 = Content.Load<Texture2D>("viking_green_death3");
            littleShipDeath4 = Content.Load<Texture2D>("viking_green_death4");
            shipDeath1 = Content.Load<Texture2D>("viking_red_death1");
            shipDeath2 = Content.Load<Texture2D>("viking_red_death2");
            shipDeath3 = Content.Load<Texture2D>("viking_red_death3");
            shipDeath4 = Content.Load<Texture2D>("viking_red_death4");
            wizardDeath1 = Content.Load<Texture2D>("wizard_death1");
            wizardDeath2 = Content.Load<Texture2D>("wizard_death2");
            thor = Content.Load<Texture2D>("Thor");
            thorhurt1 = Content.Load<Texture2D>("Thor_hurt1");
            thorhurt2 = Content.Load<Texture2D>("Thor_hurt2");
            thorhurt3 = Content.Load<Texture2D>("Thor_hurt3");
            hammer = Content.Load<Texture2D>("hammer");
            openingscreen = Content.Load<Texture2D>("opening_screen");
            thorDeath1 = Content.Load <Texture2D>("Thor_death1");
            thorDeath2 = Content.Load<Texture2D>("Thor_death2");
            thorDeath3 = Content.Load<Texture2D>("Thor_death3");
            thorDeath4 = Content.Load<Texture2D>("Thor_death4");
            thorDeath5 = Content.Load<Texture2D>("Thor_death5");

            #endregion
            //Projectile.texture = projectileTexture;

            /* This is a useful rectangle that tells you the size of your game */
            viewportrec = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);

            player = new Player(new Vector2(0, viewportrec.Height - 87), playerSprite, viewportrec, projectileTexture);//,HitBoxSprite);
            #region dictionaryTextures
            Dictionary<enemyTexture, Texture2D> enemyTextures = new Dictionary<enemyTexture, Texture2D>();
            enemyTextures.Add(enemyTexture.LittleShip, littleShip);
            enemyTextures.Add(enemyTexture.Ship, ship);
            enemyTextures.Add(enemyTexture.Wizard, wizard);
            enemyTextures.Add(enemyTexture.Thor, thor);

            Dictionary<shotTexture, Texture2D> enemyShotTextures = new Dictionary<shotTexture, Texture2D>();
            enemyShotTextures.Add(shotTexture.Bigshot, cannonball);
            enemyShotTextures.Add(shotTexture.Littleshot, littleBall);
            enemyShotTextures.Add(shotTexture.Fireball, fireball);
            enemyShotTextures.Add(shotTexture.Hammer, hammer);
            #endregion
            enemyManager = new EnemyManager(player, viewportrec, enemyTextures, enemyShotTextures); //ship,cannonball,wizard,fireball,littleShip,littleBall);



            font = Content.Load<SpriteFont>("gameFont");

            #region Sounds
            Dictionary<String, SoundEffect> sounds = new Dictionary<string,SoundEffect>();
            Dictionary<String, Song> music = new Dictionary<string, Song>();

            sounds.Add("Death",Content.Load<SoundEffect>("sound/Death"));
            sounds.Add("Electrocute", Content.Load<SoundEffect>("sound/Electrocute"));
            sounds.Add("Explosion", Content.Load<SoundEffect>("sound/explosion"));
            sounds.Add("Lightning", Content.Load<SoundEffect>("sound/lightning_1_"));
            sounds.Add("SerpentInjurefx", Content.Load<SoundEffect>("sound/SerpentInjurefx"));
            sounds.Add("Splash", Content.Load<SoundEffect>("sound/Splash"));
            sounds.Add("Thunderfx", Content.Load<SoundEffect>("sound/Thunderfx"));
            sounds.Add("VikingInjure", Content.Load<SoundEffect>("sound/VikingInjure"));
            sounds.Add("Fireball", Content.Load<SoundEffect>("sound/fireball"));

            music.Add("ForThor!", Content.Load<Song>("sound/ForThor!12"));
            music.Add("Menu", Content.Load<Song>("sound/HikingViking"));
            music.Add("Game", Content.Load<Song>("sound/NorseForce"));

            soundsManager = new SoundsManager(sounds, music);
            enemyManager.linkSoundManager(ref soundsManager);
            #endregion
            //soundsObj.loadSounds(Content.Load<Song>("sound/HikingViking"), Content.Load<SoundEffect>("sound/Splash"), Content.Load<SoundEffect>("sound/explosion"),Content.Load<Song>("sound/ForThor!12"), Content.Load<Song>("sound/SerpentInjurefx"), Content.Load<Song>("sound/Thunderfx"),Content.Load<Song>("sound/NorseForce"));

            #region artifactTextures
            artifactManager = new ArtifactManager();
            List<Texture2D> tempTextures = new List<Texture2D>();
            tempTextures.Add(wizardDeath1);
            tempTextures.Add(wizardDeath2);
            tempTextures.Add(wizardDeath1);
            tempTextures.Add(wizardDeath2);
            tempTextures.Add(wizardDeath1);
            tempTextures.Add(wizardDeath2);
            tempTextures.Add(wizardDeath1);
            tempTextures.Add(wizardDeath2);
            artifactManager.addTextureSet(EnemyType.Wizard.ToString(), tempTextures);
            tempTextures = new List<Texture2D>();
            tempTextures.Add(littleShipDeath1);
            tempTextures.Add(littleShipDeath2);
            tempTextures.Add(littleShipDeath3);
            tempTextures.Add(littleShipDeath4);
            artifactManager.addTextureSet(EnemyType.LittleShip.ToString(), tempTextures);
            tempTextures = new List<Texture2D>();
            tempTextures.Add(shipDeath1);
            tempTextures.Add(shipDeath2);
            tempTextures.Add(shipDeath3);
            tempTextures.Add(shipDeath4);
            artifactManager.addTextureSet(EnemyType.Ship.ToString(), tempTextures);
            tempTextures = new List<Texture2D>();
            tempTextures.Add(thorDeath1);
            tempTextures.Add(thorDeath2);
            tempTextures.Add(thorDeath3);
            tempTextures.Add(thorDeath4);
            tempTextures.Add(thorDeath5);
            tempTextures.Add(thorDeath4);
            tempTextures.Add(thorDeath5);
            tempTextures.Add(thorDeath4);
            tempTextures.Add(thorDeath5);
            tempTextures.Add(thorDeath4);
            tempTextures.Add(thorDeath5);
            artifactManager.addTextureSet(EnemyType.THOR.ToString(), tempTextures);
            tempTextures = new List<Texture2D>();
            tempTextures.Add(thorhurt1);
            tempTextures.Add(thorhurt2);
            tempTextures.Add(thorhurt3);
            artifactManager.addTextureSet("ThorHurt", tempTextures);
            tempTextures = new List<Texture2D>();
            tempTextures.Add(wave);
            artifactManager.addTextureSet("Wave", tempTextures);
#endregion
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        protected void prepGame(GameTime gameTime)
        {
            score = 0;
            hardMode = false;
            bombTime = TimeSpan.FromSeconds(1f);
            fireTime = TimeSpan.FromSeconds(.35f);
            enemyManager.HardMode = false;
            player.Health = 100;
            foreach (Enemy e in enemyManager.ActiveEnemies)
            {
                e.State = EnemyState.Inactive;
            }
            player.IsActive = true;
            projectileManager.Projectiles.Clear();
            enemyManager.reset();
        }

        
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit at any state
            swtichMusic();
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed
                || Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            if (gameState == GameState.StartScreen)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Space))
                {
                    gameState = GameState.PlayingScreen;
                    playingMenuMusic = false;
                    soundsManager.PlayMusic("Game");
                    previousBombTime = gameTime.TotalGameTime;
                }

            }
            else if (gameState == GameState.PlayingScreen)
            {
                

                if (!enemyManager.IsActive)
                    enemyManager.IsActive = true;
                
                enemyManager.update(gameTime);

                previousGamePadState = currentGamePadState;
                previousKeyBoardState = currentKeyboardState;

                // Read the current state.
                currentKeyboardState = Keyboard.GetState();
                currentGamePadState = GamePad.GetState(PlayerIndex.One);
                if (currentKeyboardState.IsKeyDown(Keys.H))
                {
                    enemyManager.HardMode = true;
                    hardMode = true;
                    fireTime = TimeSpan.FromSeconds(.60f);
                    bombTime = TimeSpan.FromSeconds(10f);
                }
                if (currentKeyboardState.IsKeyDown(Keys.B) && gameTime.TotalGameTime - previousBombTime > bombTime)
                {
                    previousBombTime = gameTime.TotalGameTime;
                    score -= (score / 4);
                    artifactManager.addWave();
                    foreach (Enemy e in enemyManager.ActiveEnemies)
                    {
                        e.State = EnemyState.Inactive;
                    }
                    projectileManager.ClearAll();
                }
                
                if (currentKeyboardState.IsKeyDown(Keys.Space) && gameTime.TotalGameTime - previousFireTime > fireTime)
                {
                    //soundsObj.fireSound.Play();
                    
                    // Reset our current time
                    previousFireTime = gameTime.TotalGameTime;

                    // Add the projectile, but add it to the front and center of the player
                    //259 is where the eye is
                    //Console.WriteLine("SPACEBAR - " + player.Position.X + " - " + (player.Position.X + 259));
                    float tempX;

                    if (player.Position.X + 200 > viewportrec.Width)
                    {
                        tempX = player.Position.X + 200 - viewportrec.Width;
                    }
                    else
                    {
                        tempX = player.Position.X + 200;
                    }
                    projectileManager.AddProjectile(new Projectile(player.ProjectileSprite, new Vector2(player.boundRect.X, player.Position.Y),
                        player.ProjectileVelocity, viewportrec, player.ProjectileDamage, 0.1f, Projectile.Faction.player));
                }
                player.update(gameTime);
                projectileManager.AddProjectiles(enemyManager.PendingProjectiles);
                //if (enemyManager.PendingProjectiles.Count > 1)
                //    soundsObj.explosionSound.Play();
                projectileManager.Update(gameTime);
                projectileManager.CollisionDetection(enemyManager.ActiveEnemies);
                projectileManager.CollisionDetection(player);
                if (projectileManager.playerHitThisInstant)
                {
                    //soundsObj.explosionSound.Play();
                    soundsManager.PlaySound("SerpentInjurefx");
                }
                artifactManager.addEnemiesHit(projectileManager.EnemiesHit);
                artifactManager.update(gameTime);
                foreach (Enemy e in enemyManager.DeadList)
                {
                    if (!hardMode)
                    {
                        score += e.Score;
                    }
                    else
                    {
                        score += e.Score + e.Score;
                    }
                    switch (e.Type)
                    {
                        case (EnemyType.THOR):
                                {
                                    soundsManager.PlaySound("Death");
                                    //soundsObj.thunderSound.Play();
                                    break;
                                }
                        case (EnemyType.Wizard) :
                        {
                            //score += 150;
                            //soundsManager.PlaySound("Electrocute"); //Need to trim it to be about a second long
                            break;
                        }
                        case (EnemyType.Ship):
                        {
                            //score += 100;
                            //soundsObj.fireSound.Play();
                            soundsManager.PlaySound("Splash");
                            break;
                        }
                        case (EnemyType.LittleShip):
                        {
                            //score += 25;
                            soundsManager.PlaySound("Splash");
                            break;
                        }

                    }

                }
                artifactManager.addEnemiesDeaths(enemyManager.DeadList);
                if (player.Health <= 0)
                {
                    gameState = GameState.GameOverScreen;
                }
                //enemyManager.thorActive
                
            }
               
            else if (gameState == GameState.GameOverScreen)
            {
                if (enemyManager.IsActive)
                    enemyManager.IsActive = false;

                if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                {
                    prepGame(gameTime);
                    gameState = GameState.StartScreen;
                }

            }
            else
            {
                //ERROR
            }


            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Azure);

            spriteBatch.Begin();
            if (gameState == GameState.StartScreen)
            {
                spriteBatch.Draw(openingscreen, Vector2.Zero, Color.White);
            }
            else if (gameState == GameState.PlayingScreen)
            {
                if (!hardMode)
                {
                    spriteBatch.Draw(background, Vector2.Zero, Color.White);
                }
                else
                {
                    spriteBatch.Draw(background, Vector2.Zero, Color.Red);
                }


                enemyManager.draw(spriteBatch);
                player.draw(spriteBatch);
                projectileManager.Draw(spriteBatch);
                artifactManager.Draw(spriteBatch);
                drawScore();
            }
            else if (gameState == GameState.GameOverScreen)
            {
                
                //drawScore();
                spriteBatch.Draw(endingscreen, Vector2.Zero, Color.White);
                spriteBatch.DrawString(font, "Score: " + score, new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y), Color.GreenYellow);
            }
            else
            {
                //ERROR
            }
            spriteBatch.End();

            // TODO: Add your drawing code here



            base.Draw(gameTime);
        }

        private void drawScore()
        {
            // Draw the score
            spriteBatch.DrawString(font, "Score: " + score, new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y), Color.GreenYellow);
            // Draw the player health
            if (!hardMode)
            {
                spriteBatch.DrawString(font, "Health: " + player.Health, new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + 30), Color.Red);
            }
            else
            {
                spriteBatch.DrawString(font, "Health: " + player.Health, new Vector2(GraphicsDevice.Viewport.TitleSafeArea.X, GraphicsDevice.Viewport.TitleSafeArea.Y + 30), Color.White);
            }
        }


      

    }
}
